package com.zxl.file;

import com.alibaba.fastjson.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * B站流媒体文件处理
 * @author zxl
 * @version 1.0
 * @description TODO
 * @date 2024/6/11 21:53
 */
public class BilibiliStreamFile {

    /** 配置文件名*/
    public static final String CONFIG_FILE_NAME = ".playurl";

    /** 文件原始后缀*/
    public static final String FILE_ORIGIN_SUFFIX = "m4s";

    /** 文件输出目录*/
    public static final String OUTPUT_PATH = "E:\\FFOutput";

    public static void main(String[] args) {
        try {
            handlerEntrance("E:\\DownloadBase\\bilibili");
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 处理器入口
     * @param basePath
     * @throws IOException
     */
    public static void handlerEntrance(String basePath) throws IOException {
        File file = new File(basePath);

        if (file.isDirectory()) {
            File[] files = file.listFiles();
            StringBuilder builder = new StringBuilder();
            String line = "";
            int count = 0;
            for (File temp : files){
                if (temp.isDirectory()){
                    // 读取播放配置文件信息
                    Path path = Paths.get(temp.getAbsolutePath(), CONFIG_FILE_NAME);
                    BufferedReader bufferedReader = Files.newBufferedReader(path);
                    while ((line = bufferedReader.readLine()) != null){
                        builder.append(line);
                    }
                    bufferedReader.close();
                    // 解析配置文件信息
//                      System.out.println(builder.toString());
                    JSONObject jsonObject = JSONObject.parseObject(builder.toString());
                    JSONObject data = jsonObject.getJSONObject("data");
                    JSONObject dash = data.getJSONObject("dash");
                    // 视频信息
                    JSONObject video = dash.getJSONArray("video").getJSONObject(0);
                    String videoUrl = video.getString("baseUrl");
                    copyAndTransform(temp.getAbsolutePath(), pathToFileName(videoUrl), "mp4");
                    // 音频信息
                    JSONObject audio = dash.getJSONArray("audio").getJSONObject(0);
                    String audioUrl = audio.getString("baseUrl");
                    copyAndTransform(temp.getAbsolutePath(), pathToFileName(audioUrl), "mp3");
                    // 测试代码，记得注释
                    /*if (count++ >= 0){
                        return ;
                    }*/
                }
                // 清空字符串缓存
                builder.delete(0, builder.length());
            }
        }else {
            System.err.println("提供的路径不是文件夹");
        }
    }

    /**
     * 复制并转换
     * @param filePath
     * @param fileName
     * @param suffix
     * @throws IOException
     */
    public static void copyAndTransform(String filePath, String fileName, String suffix) throws IOException {
        if (!fileName.contains(FILE_ORIGIN_SUFFIX)){
            return ;
        }
        System.out.println(fileName);
        String readPathStr = filePath + File.separator + fileName;
        String writePathStr = OUTPUT_PATH + File.separator + fileName.replaceAll(FILE_ORIGIN_SUFFIX, suffix);

        Path readPath = Paths.get(readPathStr);
        Path writePath = Paths.get(writePathStr);

        // 读通道，因为下面要从9开始，所以这里需要WRITE，否则会报错
        FileChannel readChannel = FileChannel.open(readPath, StandardOpenOption.READ, StandardOpenOption.WRITE);
        // 从索引9开始复制，已到达去除前面一堆0的目的
        MappedByteBuffer map = readChannel.map(FileChannel.MapMode.PRIVATE, 9, readChannel.size());
        // 写通道
        FileChannel writeChannel = FileChannel.open(writePath, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
        // 执行写入
        writeChannel.write(map);
        // 关闭流
        writeChannel.close();
        readChannel.close();
    }

    /**
     * 路径解析
     * @param path 完整的路径信息
     * @return 文件名称
     */
    public static String pathToFileName(String path) {
        String[] split = path.split("\\?");
        String prefix = split[0];
        return prefix.substring(prefix.lastIndexOf("/") + 1, prefix.length());
    }

}
